//
// Created by Admin on 2025/1/8.
//

#include "simple_logger.h"
#include "file_channel.h"
#include "log_writer.h"
using namespace std;

namespace slog
{
///////////////////SimpleLogger///////////////////
SimpleLogger::SimpleLogger(const std::string& loggerName)
	: _logger_name(loggerName)
	, _asyn_log_writer(std::make_shared<AsynLogWriter>())
	, _channel(std::make_shared<FileChannel>(loggerName, "", LTrace))
{

}

SimpleLogger::~SimpleLogger()
{
	_channel.reset();
}

void SimpleLogger::write(const std::shared_ptr<LogContext> &ctx)
{
	if (_asyn_log_writer)
		_asyn_log_writer->write(ctx, shared_from_this());
}

void SimpleLogger::setLevel(LogLevel level)
{
	if (_channel)
		_channel->setLogLevel(level);
}

void SimpleLogger::writeChannel(const std::shared_ptr<LogContext>& ctx)
{
	if (_channel)
		_channel->write(ctx);
}

///////////////////LogContext///////////////////
static inline const char *getFileName(const char *file) {
	auto pos = strrchr(file, '/');
#ifdef _WIN32
	if (!pos) {
		pos = strrchr(file, '\\');
	}
#endif
	return pos ? pos + 1 : file;
}

static inline const char *getFunctionName(const char *func) {
#ifndef _WIN32
	return func;
#else
	auto pos = strrchr(func, ':');
	return pos ? pos + 1 : func;
#endif
}

LogContext::LogContext(LogLevel level, const char *file, const char *function, int line)
	: _level(level)
	, _line(line)
	, _file(getFileName(file))
	, _function(getFunctionName(function))
	, _time(std::chrono::system_clock::now())
{

}

const std::string &LogContext::str()
{
	if (_got_content)
		return _content;
	_content = ostringstream::str();
	_got_content = true;
	return _content;
}

///////////////////LogContextCapture///////////////////
LogContextCapture::LogContextCapture(const SimpleLogger::Ptr &logger, LogLevel level, const char *file,
	const char *function, int line)
	: _ctx(std::make_shared<LogContext>(level, file, function, line))
	, _logger(logger)
{

}

LogContextCapture::LogContextCapture(const LogContextCapture &that)
	: _ctx(that._ctx)
	, _logger(that._logger)
{
	const_cast<LogContext::Ptr &>(that._ctx).reset();
}

LogContextCapture::~LogContextCapture() {
	*this << std::endl;
}

LogContextCapture &LogContextCapture::operator<<(std::ostream &(*f)(std::ostream &)) {
	if (!_ctx) {
		return *this;
	}
	if (!_logger.expired())
		_logger.lock()->write(_ctx);
	_ctx.reset();
	return *this;
}

void LogContextCapture::clear() {
	_ctx.reset();
}

}